package com.hmkj.core.eolinker.endpoints;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.hmkj.boot.utils.SpringContextUtils;
import com.hmkj.common.utils.StringUtils;
import com.hmkj.core.constant.CacheID;
import com.hmkj.core.constant.ConfigNID;
import com.hmkj.core.eolinker.base.EndPoint;
import com.hmkj.core.eolinker.models.*;
import com.hmkj.core.exception.BussinessException;
import com.hmkj.core.service.cache.RedisService;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.util.List;

/**
 * Created by 陌上人 on 2077/7/7 19:52.
 * 行情相关接口
 */
@Slf4j
public class QuotationEndpoint extends EndPoint {

    static RedisService redisService = SpringContextUtils.getBean(RedisService.class);

    /**
     * 查询股票的实时行情数据
     *
     * @param stockCode 股票代码
     * @return 实时行情数据
     */
    public static ModelRealTime realtime(String stockCode) throws Exception {
        if (StringUtils.isBlank(stockCode)) {
            throw new BussinessException("stockCode 不能为空");
        }
        ModelRealTime modelRealTime = getStockByCache(ModelRealTime.class, stockCode);
        if (null != modelRealTime && !StringUtils.isBlank(modelRealTime.getLast_price())
                && new BigDecimal(modelRealTime.getLast_price()).compareTo(BigDecimal.ZERO) > 0) {
            return modelRealTime;
        }

        String route = "/realtime?stock_code=" + stockCode;
        String result = doGet(route);
        JSONObject jsonObject = JSON.parseObject(result);
        JSONArray resultObject = (JSONArray) jsonObject.get("result");
        String data = JSON.parseObject(resultObject.get(0).toString()).getString("data");
        String msg = JSON.parseObject(resultObject.get(1).toString()).getString("msg");
        EolinkerMsg eolinkerMsg = JSON.parseObject(msg, EolinkerMsg.class);
        JSONArray objects = JSON.parseArray(data);
        if (eolinkerMsg != null && StringUtils.isNotBlank(eolinkerMsg.getError_info()) && StringUtils.isNotBlank(eolinkerMsg.getError_no()) && eolinkerMsg.getError_info().equals("OK") && eolinkerMsg.getError_no().equals("3000") && objects != null && objects.size() > 0) {
            return JSON.parseObject(JSON.parseArray(data).getString(0), ModelRealTime.class);
        } else {
            log.info("请求出错：" + eolinkerMsg.getError_info());
        }
        return null;
    }

    /**
     * 查询股票的实时行情数据
     *
     * @param stockCodes 股票代码
     */
    public static void combStock(String stockCodes) throws Exception {
        if (StringUtils.isBlank(stockCodes)) {
            throw new BussinessException("stockCodes 不能为空");
        }
        String route = "/comball?stock_code=" + stockCodes;
        String result = doGet(route);
//        log.info("result = " + result);
        JSONObject jsonObject = JSON.parseObject(result);
        JSONArray resultObject = (JSONArray) jsonObject.get("result");
        String data = JSON.parseObject(resultObject.get(0).toString()).getString("data");
        String msg = JSON.parseObject(resultObject.get(1).toString()).getString("msg");
        EolinkerMsg eolinkerMsg = JSON.parseObject(msg, EolinkerMsg.class);
        JSONArray objects = JSON.parseArray(data);
        if ("OK".equals(eolinkerMsg.getError_info()) && "3000".equals(eolinkerMsg.getError_no()) && null != objects && objects.size() > 0) {
            List<ModelRealTime> modelStocks = JSONArray.parseArray(data, ModelRealTime.class);
            modelStocks.forEach(QuotationEndpoint::putStock2Cache);
        } else {
            log.info("请求出错：" + eolinkerMsg.getError_info());
        }
    }

    public static void sortToCache(String stock_type, String sort_type) {
        if (StringUtils.isBlank(stock_type) || null == sort_type) {
            throw new BussinessException("参数不能为空");
        }

        String route = "/sort?stock_type=" + stock_type + "&sort_type=" + sort_type;
        String result = doGet(route);
        JSONObject jsonObject = JSON.parseObject(result);
        JSONArray resultObject = (JSONArray) jsonObject.get("result");
        String data = JSON.parseObject(resultObject.get(0).toString()).getString("data");
        String msg = JSON.parseObject(resultObject.get(1).toString()).getString("msg");
        EolinkerMsg eolinkerMsg = JSON.parseObject(msg, EolinkerMsg.class);
        JSONArray objects = JSON.parseArray(data);
        if ("OK".equals(eolinkerMsg.getError_info()) && "3000".equals(eolinkerMsg.getError_no()) && null != objects && objects.size() > 0) {
            List<ModelStock> modelStock1List = JSONArray.parseArray(data, ModelStock.class);
            putStockAndSort2Cache(modelStock1List, stock_type, sort_type);
        } else {
            log.info("请求出错：" + eolinkerMsg.getError_info());
        }
    }


    /**
     * 分时查询
     *
     * @param stockCode 股票代码
     * @return 股票分时数据
     */
    public static String trend(String stockCode) throws Exception {
        if (StringUtils.isBlank(stockCode)) {
            throw new BussinessException("stockCode 不能为空");
        }
        String route = "/trend?stock_code=" + stockCode;
        String result = doGet(route);
        JSONObject jsonObject = JSON.parseObject(result);
        JSONArray resultObject = (JSONArray) jsonObject.get("result");
        String data = JSON.parseObject(resultObject.get(0).toString()).getString("data");
        String msg = JSON.parseObject(resultObject.get(1).toString()).getString("msg");
        EolinkerMsg eolinkerMsg = JSON.parseObject(msg, EolinkerMsg.class);
        JSONArray objects = JSON.parseArray(data);
        if (eolinkerMsg != null && StringUtils.isNotBlank(eolinkerMsg.getError_info()) && StringUtils.isNotBlank(eolinkerMsg.getError_no()) && eolinkerMsg.getError_info().equals("OK") && eolinkerMsg.getError_no().equals("3000") && objects != null && objects.size() > 0) {
            return JSON.parseArray(data).toJSONString();
        } else {
            log.info("请求出错：" + eolinkerMsg.getError_info());
        }
        return null;
    }

    /**
     * k先查询
     *
     * @param stockCode    股票代码
     * @param period       k线周期
     *                     1 1分钟
     *                     2 5分钟
     *                     3 15分钟
     *                     4 30分钟
     *                     5 60分钟
     *                     6 日K线
     *                     7 周k线
     *                     8 月k线
     * @param request_num  请求行数
     * @param position_str 定位串
     * @return 股票k线数据
     */
    public static String kline(String stockCode, int period, int request_num, String position_str) throws Exception {
        if (StringUtils.isBlank(stockCode)) {
            throw new BussinessException("stockCode 不能为空");
        }
        if (StringUtils.isBlank(position_str)) {
            position_str = "-1";
        }
        String route = "/kline?stock_code=" + stockCode + "&period=" + period + "&request_num=" + request_num + "&position_str=" + position_str;
        String result = doGet(route);
        JSONObject jsonObject = JSON.parseObject(result);
        JSONArray resultObject = (JSONArray) jsonObject.get("result");
        String data = JSON.parseObject(resultObject.get(0).toString()).getString("data");
        String msg = JSON.parseObject(resultObject.get(1).toString()).getString("msg");
        EolinkerMsg eolinkerMsg = JSON.parseObject(msg, EolinkerMsg.class);
        JSONArray objects = JSON.parseArray(data);
        if (eolinkerMsg != null && StringUtils.isNotBlank(eolinkerMsg.getError_info()) && StringUtils.isNotBlank(eolinkerMsg.getError_no()) && eolinkerMsg.getError_info().equals("OK") && eolinkerMsg.getError_no().equals("3000") && objects != null && objects.size() > 0) {
            return JSON.parseArray(data).toJSONString();
        } else {
            log.info("请求出错：" + eolinkerMsg.getError_info());
        }
        return null;
    }

    /**
     * 指数实时报价
     *
     * @param stock_code 代码
     * @return 实时报价
     */
    public static ModelIndexRealPrice index(String stock_code) throws Exception {
        if (StringUtils.isBlank(stock_code)) {
            throw new BussinessException("stock_code 不能为空");
        }

        String route = "/index?stock_code=" + stock_code;
        String result = doGet(route);
        JSONObject jsonObject = JSON.parseObject(result);
        JSONArray resultObject = (JSONArray) jsonObject.get("result");
        String data = JSON.parseObject(resultObject.get(0).toString()).getString("data");
        String msg = JSON.parseObject(resultObject.get(1).toString()).getString("msg");
        EolinkerMsg eolinkerMsg = JSON.parseObject(msg, EolinkerMsg.class);
        JSONArray objects = JSON.parseArray(data);
        if (eolinkerMsg != null && StringUtils.isNotBlank(eolinkerMsg.getError_info()) && StringUtils.isNotBlank(eolinkerMsg.getError_no()) && eolinkerMsg.getError_info().equals("OK") && eolinkerMsg.getError_no().equals("3000") && objects != null && objects.size() > 0) {
            return JSON.parseObject(JSON.parseArray(data).getString(0), ModelIndexRealPrice.class);
        } else {
            log.info("请求出错：" + eolinkerMsg.getError_info());
        }
        return null;
    }

    /**
     * 查询股票列表
     *
     * @param stock_type   市场类别
     * @param request_num  定位串，传空默认为20
     * @param position_str 起始位空，从应答中获取
     * @return 股票列表
     */
    public static String list(Integer stock_type, String request_num, String position_str) throws Exception {
        if (null == stock_type) {
            stock_type = StockType.SHEN_A;
        }
        if (StringUtils.isBlank(request_num)) {
            request_num = "2";
        }
        if (StringUtils.isBlank(position_str)) {
            position_str = "0";
        }
        String route = "/list?stock_type=" + stock_type + "&request_num=" + request_num + "&position_str=" + position_str;
        String result = doGet(route);
        JSONObject jsonObject = JSON.parseObject(result);
        JSONArray resultObject = (JSONArray) jsonObject.get("result");
        String data = JSON.parseObject(resultObject.get(0).toString()).getString("data");
        String msg = JSON.parseObject(resultObject.get(1).toString()).getString("msg");
        EolinkerMsg eolinkerMsg = JSON.parseObject(msg, EolinkerMsg.class);
        JSONArray objects = JSON.parseArray(data);
        if (eolinkerMsg != null && StringUtils.isNotBlank(eolinkerMsg.getError_info()) && StringUtils.isNotBlank(eolinkerMsg.getError_no()) && eolinkerMsg.getError_info().equals("OK") && eolinkerMsg.getError_no().equals("3000") && objects != null && objects.size() > 0) {
            return JSON.parseArray(data).toJSONString();
        } else {
            log.info("请求出错：" + eolinkerMsg.getError_info());
        }
        return null;
    }

    /**
     * 从缓存中获取股票信息
     *
     * @param tClass    返回的类型
     * @param stockCode 股票代码
     * @param <T>       返回的类型
     * @return 股票信息
     */
    private static <T> T getStockByCache(Class<T> tClass, String stockCode) {
        // 股票缓存默认间隔时间为10分钟
        String minute = redisService.get(ConfigNID.STOCK_CACHE_TIME);
        if (minute == null) {
            minute = "10";
        }
        // 保存的股票key，用来进行股票查询，过期之后则不查询
        String keys = redisService.get(CacheID.STOCK_KEYS + stockCode);
        if (keys != null) {
            redisService.expire(CacheID.STOCK_KEYS + stockCode, 60 * Integer.valueOf(minute));
            // 缓存的股票信息,过期后自动删除
            ModelRealTime modelRealTime = redisService.get(CacheID.STOCK_CACHE + stockCode, ModelRealTime.class);
            if (modelRealTime != null) {
                return JSONObject.parseObject(JSONObject.toJSONString(modelRealTime), tClass);
            }
        } else {
            redisService.put(CacheID.STOCK_KEYS + stockCode, stockCode, 60 * Integer.valueOf(minute));
        }
        return null;
    }

    /**
     * 把股票信息放入缓存
     *
     * @param modelRealTime 股票信息json
     */
    public static void putStock2Cache(ModelRealTime modelRealTime) {
        String minute = redisService.get(ConfigNID.STOCK_CACHE_TIME);
        redisService.put(CacheID.STOCK_CACHE + modelRealTime.getStock_code(), modelRealTime, 60 * Integer.valueOf(minute));
    }

    /**
     * 把股票信息放入缓存(sort)
     */
    public static void putStockAndSort2Cache(List<ModelStock> modelStock1List, String stock_type, String sort_type) {
        String minute = redisService.get(ConfigNID.STOCK_CACHE_TIME);
        redisService.put(CacheID.STOCK_SORT_CACHE + stock_type + ":" + sort_type, modelStock1List, 60 * Integer.valueOf(minute));
    }

    public static void main(String[] args) {
        try {
//            System.out.println(index("1A0001"));
//            System.out.println(kline("000001",1,10,"-1"));
            System.out.println(list(StockType.STARTUPS, "10000", "0"));
//            System.out.println(realtime("300635"));
//            System.out.println(realtime("600133"));
//            System.out.println(list(3,"20",""));
//            String uuid = UUID.randomUUID().toString();
//            System.out.println(uuid);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
